sed & gawk

쉘 스크립트가 가장 많이 사용되는 업무는 로그 검사, 구성 파일 검사 등 텍스트 파일을 조작하는 작업이다.
리눅스에서 사용가능한 sed 와 gawk를 사용하면, 데리터 처리 작업을 단순하게 처리할 수 있다.

텍스트 요소에 대한 서식화, 삽입, 변경, 삭제를 자동으로 할 수 있는 커맨드라인 편집기
sed 편집기
일반적인 대화형 텍스트 편지기와 반대 개념인 스트림 편집기

vim과 같은 대화형 텍스트 편지기는 키보드를 사용한 상호작용으로 텍스트의 삽입, 삭제, 바꾸기 작업 등을 처리한다.
스트림 편집기는 편집기가 데이터를 처리하기 전에 미리 제공 받은 일련의 규칙에 따라 데이터의 스트림을 편집한다.

1. 입력 수단으로부터 한 번에 하나씩 데이터 줄을 읽음
2. 제공된 편집기 명령으로 데이터를 대조
3. 명령에서 지정된 대로 스트림의 데이터를 변경
4. STDOUT으로 새로운 데이터를 출력
sed options script file
options
-e script: 입력을 처리하는 동안 실행 중인 명령에 스크립트 지정된 명령을 추가
-f file: 입력을 처리하는 동안 실행 중인 파일에 지정된 명령을 추가
-n: 각 명령에 대한 출력을 만들지 않지만, print 명령을 기다림
echo "This is a sentence" | sed 's/sentence/beautiful sentence/'
echo 'dog is my favorite animal with brown color!' > data.txt
sed 's/dog/cat/' data.txt
기본적으로 sed는 STDIN 입력 스트림에 대해 지정된 명령을 적용한다.
명령을 수행한 스트림은 sed의 STDOUT으로 출력
sed -e 's/brown/green/; s/dog/cat/' data.txt
sed -e '
s/brown/green/
s/with/without/
s/dog/cat' data.txt #
-e 명령을 이용해서 커맨드라인에서 하나 이상의 명령을 실행할 수 있다.
echo -e 's/browm/green/\ns/with/without/\ns/dog/cat/\n' > script.sed
sed -f script.sed data.txt
gawk
gawk는 sed 편집기보다 파일의 데이터를 수정하고 재구성할 수 있는 좀 더 프로그래밍에 가까운 환경을 제공하는
고급 데이터 조작 도구이다.

gawk는 기존의 UNIX에서 사용하더 awk의 GNU 버전이다.

기능
- 데이터를 저장하는 변수 정의
- 데이터를 다룰 수 있도록 산술 및 문자열 연산자 사용
- if-then 및 루프문과 같이 데이터 처리에 로직을 추가하는 구조적 프로그래밍 개념 사용
- 데이터 파일 안에서 데이터 요소를 추출하고 다른 순서 또는 형식으로 재구성하여 형식화된 보고서 생성

gawk를 이용하면, 복잡한 로그 파일의 오류 줄을 찾아내고 이를 읽기 쉬운 서식으로 형식화 할 수 있다.
gawk options program file
options
- F fs: 파일 구분자를 지정(한줄에서 데이터 필드 경계)
-f file: 프로그램이 읽어 들일 파일 이름을 지정
-var=value: 사용할 변수의 기본값을 정의
-mf N: 처리할 필드의 최대 수를 지정
-mr N: 데이터 파일의 최대 레코드 크기를 지정
-W keyword: 호환성 모드 또는 경고 수준을 지정

gawk는 괄호 ( { } )를 사용해서 명령어를 구분한다.
gawk는 STDIN으로 데이터를 입력받으며, STDIN 을 대기한다.(버퍼 제공함 <Enter> 입력 후, 데이터 처리를 시작 함
gawk는 EOF을 입력으로 받을 때까지 입력을 받으며, <Ctrl>+<D> 키를 통해 이를 입력할 수 있다.
echo 'My name is Rick' | gawk '{$4="SIAN"; print $0}'
echo 'My name is Rick' | gawk '{
$4="SIAN"
print $0
}'
data field variables
$0: 텍스트 스트림의 전체 줄
$1: 텍스트의 줄에서 첫 번째 데이터 필드
$2: 텍스트의 줄에서 두 번째 데이터 필드
$n: 텍스트의 줄에서 n 번째 데이터 필드
텍스트는 필드 구분자로 구분되면 Default로 white space(space or tab)을 구분자로 사용한다.
echo -en 'first line\nsecond line\nthird line' > tmp.txt
gawk '{print $1}' tmp.txt
rm tmp.txt
-F 옵션을 이용해 필드 구분자를 지정
gawk -F: '{print $1}' /etc/passwd
sed와 마찬가지로, 파일을 통해 명령을 전달 받을 수 있다.
echo -e "{print \$1 \"'s home directory is \" \$6}" > script.gawk
echo -e "{\ntext=\"'s home directory is \"\nprint \$1 text \$6\n}" > script2.gawk
gawk -F: -f script.gawk /etc/passwd
gawk -F: -f script2.gawk /etc/passwd
rm script.gawk script2.gawk
gawk에서 변수를 참조할 때, 쉘 스크립트와 달리 ' $ '를 사용하지는 않음

BEGIN 키워드를 이용해 데이터 처리하기 전에 스크립트를 실행시킬 수 있음
(gawk는 원래 스트림을 한 줄씩 받고, 이에 스크립트를 실행시킴)
gawk 'BEGIN {print "Hello world!"}' #
echo -e 'Line 1\nLine 2\nLine 3' > tmp.txt
gawk 'BEGIN {print "Contents: "}; {print $0}; END {print "End of File"}' tmp.txt
rm tmp.txt
Contents:
Line 1
Line 2
Line 3
End of File
echo -e 'BEGIN {
print "The latest list of users and shells"
print "UserID\tShell"
print"----------\t------"
FS=":" #
}
{
print $1" \t"$7
}
END {
print "This concludes the listing"
}' > script.gawk
gawk -f script.gawk /etc/passwd
rm script.gawks
BEGIN 내부에서 FS 변수를 이용해서 필드 구분자를 지정할 수 있다.